package sync

import (
	"api/libs/errs"
	"encoding/json"
	"fmt"
	"github.com/nsqio/go-nsq"
)

func NewPubConfig(topic string) *PubConfig {
	return &PubConfig{
		Topic: topic,
	}
}

func (ms *ModelSync) InitProducer() {
	configNsq := nsq.NewConfig()
	var err error
	ms.producer, err = nsq.NewProducer(ms.NsqPubAddr, configNsq)
	if errs.Try(err) {
		return
	}
	ms.producer.SetLoggerLevel(nsq.LogLevelError)
}

func (ms *ModelSync) Pub(conf *PubConfig) (err error) {
	err = ms.producer.Publish(conf.Topic, conf.Data)
	return
}

func (ms *ModelSync) PubInitNeed(pubName string, model string) (err error) {
	data := &InitNeed{
		SubName:   ms.ServiceName,
		ModelName: model,
	}
	conf := NewPubConfig(fmt.Sprintf("%s.%s.%s", SYNC_PREFIX, TOPIC_INIT_NEED, pubName))
	conf.SetAndJson(data)
	return ms.Pub(conf)
}

func (ms *ModelSync) PubInitFeed(in *InitNeed, model interface{}) (err error) {
	md := &ModelData{
		Id:      ms.GetIdFromInterface(model),
		Crud:    CRUD_C, //初始化都发布C创建
		PubName: ms.ServiceName,
	}
	md.SetAndJson(model)
	data := &InitFeed{
		Need: in,
		Data: md,
	}
	conf := NewPubConfig(fmt.Sprintf("%s.%s.%s_%s",
		SYNC_PREFIX, TOPIC_INIT_FEED,
		ms.ServiceName, in.SubName))
	conf.SetAndJson(data)
	return ms.Pub(conf)
}

func (ms *ModelSync) PubCrud(modelName string, crud string, v interface{}) (err error) {
	data := &ModelData{
		Id:        ms.GetIdFromInterface(v),
		Crud:      crud,
		PubName:   ms.ServiceName,
		ModelName: modelName,
	}
	data.SetAndJson(v)
	conf := NewPubConfig(fmt.Sprintf("%s.%s.%s.%s", SYNC_PREFIX, TOPIC_CRUD, ms.ServiceName, modelName))
	conf.SetAndJson(data)
	return ms.Pub(conf)
}

func (ms *ModelSync) PubCrudCreate(modelName string, v interface{}) (err error) {
	return ms.PubCrud(modelName, CRUD_C, v)
}

func (ms *ModelSync) PubCrudUpdate(modelName string, v interface{}) (err error) {
	return ms.PubCrud(modelName, CRUD_U, v)
}

func (ms *ModelSync) PubCrudDelete(modelName string, v interface{}) (err error) {
	return ms.PubCrud(modelName, CRUD_D, v)
}

type PubConfig struct {
	Topic string
	Data  []byte
}

func (pc *PubConfig) Set(data []byte) *PubConfig {
	pc.Data = data
	return pc
}

func (pc *PubConfig) SetString(data string) *PubConfig {
	pc.Data = []byte(data)
	return pc
}

func (pc *PubConfig) SetAndJson(data interface{}) *PubConfig {
	content, e := json.Marshal(data)
	if e != nil {
		println(e)
		pc.Data = []byte(e.Error())
		return pc
	}
	pc.Data = content
	return pc
}
